//! mod Search
//! 检索功能主模块
//!

use std::path::Path;

/// 检索执行器
#[derive(Debug)]
pub struct Runner {
    path: Option<String>,
    keyw: Option<String>,
    flag: Option<String>,
}

impl Runner {
    #[inline]
    pub fn from_env_args() -> Runner {
        let path = std::env::args().nth(1);
        let keyw = std::env::args().nth(2);
        let flag = std::env::args().nth(3);
        Runner { path, keyw, flag }
    }

    pub fn check_params(&self) -> &Self {
        if let None = self.path {
            println!("请输入检索路径");
            std::process::exit(0);
        }

        if let None = self.keyw {
            println!("关键词未设置，将检索所有文件");
        }

        self
    }

    /// 递归获取目录下所有文件
    #[inline]
    pub fn seek_matched_files(&self) {
        if let Some(input_path) = &self.path {
            let path_handler = Path::new(input_path);

            if !path_handler.is_dir() {
                println!("检索的路径必须是目录");
                std::process::exit(0);
            }

            let all_content = Self::get_dir_content(input_path);
            for entry in &all_content {
                if Self::match_files(self, entry) {
                    println!("{:?}", entry);
                }
            }
        }
    }

    /// 匹配符合条件的文件
    #[inline]
    fn match_files(&self, entry: &String) -> bool {
        // 没有设置匹配内容，则输出所有[文件/目录]列表
        if let None = &self.keyw {
            return true;
        }
        if let Some(keyw) = &self.keyw {
            return match &self.flag {
                None => entry.contains(keyw),
                Some(flag) => Self::check_entry_with_flags(&self, entry, keyw, flag),
            };
        }
        false
    }

    /// 使用了 flag 的匹配
    fn check_entry_with_flags(&self, entry: &String, keyw: &String, flag: &String) -> bool {
        match flag.as_str() {
            "--ext" => {
                let path = Path::new(&entry);
                if !path.is_file() {
                    return false;
                };
                if let Some(ext) = path.extension() {
                    return keyw == ext.to_str().unwrap();
                };

                false
            }

            "--dir" => {
                let path = Path::new(&entry);
                if !path.is_dir() {
                    return false;
                };

                entry.contains(keyw)
            }

            "--file" => {
                let path = Path::new(&entry);
                if !path.is_file() {
                    return false;
                };

                entry.contains(keyw)
            }
            _ => {
                println!("使用了未定义的匹配选项!");
                std::process::exit(0);
            }
        }
    }

    /// 读取目录下所有内容
    fn get_dir_content(path: &String) -> Vec<String> {
        let path = Path::new(path);
        let mut res: Vec<String> = Vec::new();
        for entry in path
            .read_dir()
            .expect(&format!("读取{:?}路径下内容失败", path))
        {
            if let Ok(entry) = entry {
                if let Some(path) = entry.path().as_path().to_str() {
                    res.push(path.to_string()); //加入路径集合
                }

                // 获取[文件/目录]信息
                let file_type = entry
                    .file_type()
                    .expect(&format!("读取{:?}文件信息失败", entry.path()));

                if file_type.is_dir() {
                    // 遍历后继续添加路径
                    if let Some(path) = entry.path().as_path().to_str() {
                        res.extend_from_slice(&Self::get_dir_content(&path.to_string()));
                    }
                }
            }
        }

        res
    }
}
